/************************************************************************/
/* Game                                                                 */
/************************************************************************/
#include "Game/Game Objects/Towers/BaseTower.h"

namespace TD_Game {

	/************************************************************************/
	/* Default values                                                       */
	/************************************************************************/
	const unsigned int BaseTower::evolutionTime[NUMBER_OF_LEVELS]	= {1500, 3500, 7000, 9000, 15000, 0};

	

	/************************************************************************/
	/* Private functions                                                    */
	/************************************************************************/
	void BaseTower::deleteShots() {
		vector<BaseShot *>::iterator iter;
		for(iter = m_shotVector.begin(); iter != m_shotVector.end();) { 
			if (*iter != NULL) {
				if((*iter)->isFinished()) {
					delete *iter;
					iter = m_shotVector.erase(iter);
				} else {
					++iter;
				}
			}

		}
	}

	/************************************************************************/
	/* Protected functions                                                  */
	/************************************************************************/

	void BaseTower::initValues() {
		m_towerLvl = 1;
		m_pDescriptionTile = NULL;
		m_isShooting = false;

	}
	void BaseTower::update(unsigned int deltaTime) {
		//Always Update teh shots
		for(unsigned int i = 0; i < m_shotVector.size(); i++) {
			m_shotVector[i]->update(deltaTime);
		}

		if(!m_isUpgrading && !m_isSelling) {
			

			//Updating last tick
			m_lastTick += deltaTime;
			m_pCreeps = & MarioManager::getInstance()->getObjectMap();

			if(m_pTarget == NULL || MarioManager::getInstance()->getMarioByID(m_targetID) == NULL || m_pTarget->isDying() || m_pTarget->isDead()) {
				map<unsigned int, BaseMario *>::const_iterator iter = m_pCreeps->begin();
				while(iter != m_pCreeps->end() && m_pCreeps->size() > 0) { //Iterate through the creeps
					if(Coord2D::DistanceBetween(iter->second->getPosition(), m_position) < getTowerRange()) {
						//Selects the first creep within the radius
						if(!iter->second->isDying() && !iter->second->isDead()) {
							m_pTarget = iter->second;
							m_targetID = iter->first;
							break;
						} else {
							m_pTarget = NULL;
						}
					}
					iter++;
				}
			} 

			if (m_pTarget != NULL &&  MarioManager::getInstance()->getMarioByID(m_targetID) != NULL ) {
				if((getShootingInterval() - m_pAnimationSet->getAnimation("Shooting_L")->getTotalAnimationTime()) - m_lastTick <= 0) {
					//If it should start the shooting animation
					if(!m_isShooting) {
						m_isShooting = true;

						//Check if should be shooting leftwards or rightwards
						if(m_pTarget->getPosition().x - m_position.x >= 0 ) {
							m_pAnimationSet->setCurrentAnimation("Shooting_R");
						} else {
							m_pAnimationSet->setCurrentAnimation("Shooting_L");
						}

						if(m_pAnimationSet->getCurrentAnimation() != NULL) {
							m_pAnimationSet->getCurrentAnimation()->resetAnimation();
						}

						//Last tick correction:
						m_lastTick = getShootingInterval() - m_pAnimationSet->getAnimation("Shooting_L")->getTotalAnimationTime();
						m_lastTick += deltaTime;
					}
				}
				if(getShootingInterval() - m_lastTick <= 0) { //If the turret firing cooldown was respected
					if(m_isShooting) {
						//If it has started shooting.
						shoot();
						m_lastTick = 0;
						m_isShooting = false;
						m_pTarget = NULL;
					} else if(Coord2D::DistanceBetween(m_pTarget->getPosition(), m_position) < getTowerRange()) { 
						m_pTarget = NULL;
						m_isShooting = false;
					} 
				} else if(!m_isShooting) {
					if(m_pAnimationSet->getCurrentAnimation() != NULL && m_pAnimationSet->getCurrentAnimation()->getName() == "Shooting") {
						if(m_pAnimationSet->getCurrentAnimation()->isFinished()) {
							m_pAnimationSet->setCurrentAnimation("Idle");
						}
					} else {
						m_pAnimationSet->setCurrentAnimation("Idle");
					}

				}
			} else { // No target, rest
				if(m_pAnimationSet->getCurrentAnimation() != NULL && m_pAnimationSet->getCurrentAnimation()->getName() == "Shooting") {
					if(m_pAnimationSet->getCurrentAnimation()->isFinished()) {
						m_pAnimationSet->setCurrentAnimation("Idle");
						m_isShooting = false;
					}
				} else {
					m_pAnimationSet->setCurrentAnimation("Idle");
					m_isShooting = false;
				}

			}
		}
		
	}

	void BaseTower::shoot() {
		m_shotVector.push_back(ShotFactory::createBaseShot(shotTypes(m_baseShotType + m_towerLvl - 1), m_position, getTowerDamage(), m_pTarget, m_targetID));
	}


	/************************************************************************/
	/* ctors and dtors                                                      */
	/************************************************************************/

	BaseTower::BaseTower() {
		//Variable default initialization
		
		m_pTarget = NULL;
		m_lastTick = 0;

		initValues();
	}

	BaseTower::BaseTower(const BaseTower &rhs) {
		
	}

	BaseTower & BaseTower::operator =(const BaseTower &rhs) {
		return(*this);
	}

	BaseTower::BaseTower(unsigned int g_ID, const Coord2D & turretPosition) : BaseEntity(turretPosition) {
		m_ID = g_ID;
		
		m_pTarget = NULL;
		m_targetID = -999999;

		//Default 
		m_lastTick = 0;
		m_pAnimationSet = NULL;

		initValues();

		m_isUpgrading = m_isSelling = m_wasSold = false;
		m_upradingTick = 0;
		m_pProgressBar = NULL;
	}

	BaseTower::~BaseTower() {
		Utils::safeDelete<AnimationSet>(m_pAnimationSet);
		Utils::safeDelete<ProgressBar>(m_pProgressBar);
		Utils::safeDelete<Tile>(m_pDescriptionTile);
		vector<BaseShot *>::iterator iter;
		for(iter = m_shotVector.begin(); iter != m_shotVector.end();) { 	
			if(dynamic_cast<StandardShot *>(*iter)) {
				Utils::safeDelete<StandardShot>(dynamic_cast<StandardShot *>(*iter));
			} else {	
				delete *iter;
			}
			iter = m_shotVector.erase(iter);
		}
	} 

	/************************************************************************/
	/* Functionalities                                                      */
	/************************************************************************/
	void BaseTower::upgradeLevel() {
		if(!m_isSelling && !m_isUpgrading && !m_wasSold) {
			if(m_towerLvl <= NUMBER_OF_LEVELS) {
				m_pAnimationSet->setCurrentAnimation("Upgrading");
				++m_towerLvl;	
				m_isUpgrading = true;
				float progressSpeed = (30.0/(evolutionTime[m_towerLvl - 2]/1000.0));
				if(m_pProgressBar == NULL) {
					m_pProgressBar = new ProgressBar(m_position + m_upBarDisplacement, Coord2D(30, 5), progressSpeed/frameRate);
				} else {
					m_pProgressBar->setSpeed(progressSpeed);
					m_pProgressBar->restartProgress();
				}
			}
		}
	}

	void BaseTower::sell() {
		if(!m_isUpgrading && !m_wasSold && !m_isSelling) {
			m_isSelling = true;
			float progressSpeed = (30.0/(evolutionTime[0]/1000.0));
			if(m_pProgressBar == NULL) {
				m_pProgressBar = new ProgressBar(m_position + m_upBarDisplacement, Coord2D(30, 5), progressSpeed/frameRate);
			} else {
				m_pProgressBar->setSpeed(progressSpeed);
				m_pProgressBar->restartProgress();
			}
		}
	}

	void BaseTower::render(SDL_Surface *const g_destSurface, unsigned int deltaTime) {

		vector<BaseShot *>::iterator iter;
		for(iter = m_shotVector.begin(); iter != m_shotVector.end(); ) { 
			if ((*iter) != NULL) {
				if((*iter)->isFinished()) {
					delete *iter;
					iter = m_shotVector.erase(iter);
				} else {
					(*iter)->render(g_destSurface, deltaTime);
					++iter;
				}
			}
		}
		if(!m_isUpgrading && !m_isSelling) {
			if(m_pAnimationSet != NULL) {
				m_pAnimationSet->render(g_destSurface, deltaTime, m_position);
			}
		} else {
			m_upradingTick += deltaTime;
			if(m_pProgressBar->isFull()) {
				if(m_isUpgrading) {
					m_isUpgrading = false;
					m_upradingTick = 0;
					pSound = TD_Resources::ResourceManager::loadSound("SFX/sounds/Power Up.wav");
					pSound->playSound(false);
					if(m_pProgressBar != NULL) {
						delete m_pProgressBar;
						m_pProgressBar = NULL;
					}
					AnimationSet *oldAnimationSet = m_pAnimationSet;
					AnimationSet *oldBaseShotAnimationSet = m_pBaseShotAS; 
					m_pAnimationSet = AnimationSetFactory::createTowerAnimationSet(towerTypes(m_baseTowerType + m_towerLvl - 1), "Idle");
					m_pBaseShotAS = AnimationSetFactory::createShotAnimationSet(shotTypes(m_baseShotType + m_towerLvl - 1), "Moving");
					
					if(dynamic_cast<StandardAnimationSet *>(oldAnimationSet)) {
						Utils::safeDelete<StandardAnimationSet>(dynamic_cast<StandardAnimationSet *>(oldAnimationSet));
					} else {
						Utils::safeDelete<AnimationSet>(oldAnimationSet);
					}

					if(dynamic_cast<StandardAnimationSet *>(oldBaseShotAnimationSet)) {
						Utils::safeDelete<StandardAnimationSet>(dynamic_cast<StandardAnimationSet *>(oldBaseShotAnimationSet));
					} else {
						Utils::safeDelete<AnimationSet>(oldBaseShotAnimationSet);
					}

				} else if(m_isSelling) {
					m_wasSold = true;
					m_sellingTick = 0;
				}
			} else {
				if(m_pAnimationSet != NULL) {
					m_pAnimationSet->render(g_destSurface, deltaTime, m_position);
				}
				m_pProgressBar->render(g_destSurface, deltaTime);
			}
		}
	}
}